package com.puzzlebazar.client.puzzle.model;

import com.google.gwt.user.client.Timer;


public class MoveTimerRealtime extends MoveTimerImpl {

	private final MyTimer timer = new MyTimer();
	private long timeOffset;
	private long speed = 1;

	/**
	 * Create a realtime timer starting at 0
	 */
	public MoveTimerRealtime() {
		timeOffset = 0;
	}

	/**
	 * Creates a realtime timer starting at the specified time
	 * 
	 * @param startingTime Starting time
	 */
	public MoveTimerRealtime( long startingTime ) {
		timeOffset = startingTime;
	}
	
	private class MyTimer extends Timer {

		private long startTime = -1;

		@Override
		public void run() {
			setChanged();
			notifyObservers();
		}

		@Override
		public void cancel() {
			super.cancel();
			startTime = -1;
		}
		
		@Override
		public void schedule(int delayMillis) {
			super.schedule(delayMillis);
			setStartTime();
		}

		@Override
		public void scheduleRepeating(int delayMillis) {
			super.scheduleRepeating(delayMillis);
			setStartTime();		
		}

		private void setStartTime() {
			startTime = System.currentTimeMillis();
		}

		/**
		 * Access the current time of this timer in milliseconds
		 */
		public long getCurrTime() {
			if( startTime == -1 )
				return 0;
			return System.currentTimeMillis() - startTime;
		}
		
	}

	@Override
	public boolean isRunning() {	
		return timer.startTime != -1;
	}
	
	@Override
	public void start() {
		if( isRunning() )
			return;
		timer.cancel();
		timer.scheduleRepeating( 25 );
		setChanged();
	}
		
	@Override
	public void stop() {
		if( !isRunning() )
			return;
		timeOffset = peekTime();
		timer.cancel();
		setChanged();
	}

	@Override
	public void step() {
		if( isRunning() )
			return;
		timeOffset += ((int)(speed/2))*125;
		setChanged();
	}
	
	@Override
	public void set( long time ) {
		timeOffset = time - timer.getCurrTime() * speed;
		setChanged();
	}

	@Override
	public long peekTime() {
		return timeOffset + timer.getCurrTime() * speed;
	}	
	
	@Override
	public void release() {
		super.release();
		timer.cancel();
	}

	@Override
	public long getSpeed() {
		return speed;
	}

	@Override
	public void setSpeed(long speed) {
		if( this.speed == speed || speed < 1 )
			return;
		setChanged();
		if( !isRunning() )
			this.speed = speed;
		else {
			stop();
			this.speed = speed;
			start();
		}
	}
	
}
